<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			svg {
				border: 1px solid #CCCCCC;
			}


			.model {
				/* font-size: 12px;
				transform: scale(0.63,0.63) ;
				*font-size: 10px; */
				/* background-color: #0000FF; */
				border: 2px solid #323232;
				border-radius: 4px;
				/* position: absolute; */
				background-color: #fff;
				-webkit-user-select: none;
				-moz-user-select: none;
				-ms-user-select: none;
				user-select: none;
			}

			.tablename:hover {
				/* background-color: #F0F8FF; */
				cursor: move;
			}

			.model .tablename {
				font-size: 10px;
				font-weight: bold;
				border-bottom: 2px solid #323232;
				padding: 2px 3px 3px 2px;
				text-align: center;
			}

			.model .columns {
				padding: 5px;
			}

			.model .columns ul {
				list-style-type: none;
				padding: 0px;
				margin: 0px;
				font-size: 10px;
				/* font-weight: 500; */
			}

			.model .columns ul li {
				text-indent: 2px;
				overflow: hidden;
				/* min-height: 18px; */
			}
		</style>
	</head>
	<body>
		<svg id="s" version="1.1" baseProfile="full" width="100%" height="1000" xmlns="http://www.w3.org/2000/svg">
			<g id="g1" transform="translate(100,100)">
				<foreignobject class="node" x="0" y="0" width="200px" height="100%">
					<div id="box" class="model">
						<div class="tablename">
							子公司月度销售金额（不含税）<br />
							DM_SALES_MONTH_AMOUNT
						</div>
						<div class="columns">
							<ul>
								<li>🔑 COMPANY_CODE  -  公司代码</li>
								<li>🔑 COMPANY_NAME  -  公司名称</li>
								<li>COMOPANY_SHORTNAME  -  公司简称</li>
								<li>ACCOUNT_TITLE_CATEGORY  -  科目分类 </li>
								<li>YEAR_MONTH  -  年月</li>
								<li>AMOUNT - 金额</li>
								<li>DAY  -  过账日期</li>
								<li>FISAL_YEAR  -  会计年度</li>
							</ul>
						</div>
					</div>
				</foreignobject>
			</g>
			<circle cx="300" cy="220" r="5" stroke="black" stroke-width="1" fill="#fff" />

			<g id="g2" transform="translate(400,100)">
				<foreignobject class="node" x="0" y="0" width="200px" height="300px">
					<div id="box" class="model">
						<div class="tablename">
							子公司月度销售金额（不含税）<br />
							DM_SALES_MONTH_AMOUNT
						</div>
						<div class="columns">
							<ul>
								<li>🔑 COMPANY_CODE  -  公司代码</li>
								<li>🔑 COMPANY_NAME  -  公司名称</li>
								<li>COMOPANY_SHORTNAME  -  公司简称</li>
								<li>ACCOUNT_TITLE_CATEGORY  -  科目分类 </li>
								<li>YEAR_MONTH  -  年月</li>
								<li>AMOUNT - 金额</li>
								<li>DAY  -  过账日期</li>
								<li>FISAL_YEAR  -  会计年度</li>
							</ul>
						</div>
					</div>
				</foreignobject>
			</g>
			<circle cx="400" cy="220" r="5" stroke="black" stroke-width="1" fill="fff" />

			<!-- <g id="g2" transform="translate(100,100)">
				<rect width="100" height="100" rx="2" style="fill:#ffffff;stroke-width:1;stroke:#CCCCCC" />
				<text x="0" y="15" style="font-size: 12px;" fill="#666">input_wms_entry</text>
				<text x="0" y="35" style="font-size: 12px;" fill="#666">WMS入库</text>
				<line x1="0" y1="45" x2="100" y2="45" style="stroke:#cccccc;stroke-width:1" />
			</g> -->

			<defs>
				<marker id='markerArrow' markerWidth='13' markerHeight='13' refx='2' refy='6' orient='auto'>
					<path d='M2,2 L2,11 L10,6 L2,2' style='fill:#000' />
				</marker>
			</defs>
			

			<line x1='100' y1='50' x2='200' y2='50' stroke='#000' stroke-width='1' marker-end='url(#markerArrow)'>
			</line>
			
			<line x1='100' y1='50' x2='300' y2='150' stroke='#000' stroke-width='1' marker-end='url(#markerArrow)'>
			</line>
			
		</svg>
	</body>
</html>

<script type="text/javascript">
	var SVG_NS = "http://www.w3.org/2000/svg"


	// Makes an element in an SVG document draggable.
	// Fires custom `dragstart`, `drag`, and `dragend` events on the
	// element with the `detail` property of the event carrying XY
	// coordinates for the location of the element.
	function makeDraggable(el) {
		if (!el) return console.error('makeDraggable() needs an element');
		var svg = el;
		while (svg && svg.tagName != 'svg') svg = svg.parentNode;
		if (!svg) return console.error(el, 'must be inside an SVG wrapper');
		var pt = svg.createSVGPoint(),
			doc = svg.ownerDocument;

		var root = doc.rootElement || doc.body || svg;
		var xlate, txStartX, txStartY, mouseStart;
		var xforms = el.transform.baseVal;

		el.addEventListener('mousedown', startMove, false);

		function startMove(evt) {
			// We listen for mousemove/up on the root-most
			// element in case the mouse is not over el.
			root.addEventListener('mousemove', handleMove, false);
			root.addEventListener('mouseup', finishMove, false);

			// Ensure that the first transform is a translate()
			xlate = xforms.numberOfItems > 0 && xforms.getItem(0);
			if (!xlate || xlate.type != SVGTransform.SVG_TRANSFORM_TRANSLATE) {
				xlate = xforms.createSVGTransformFromMatrix(svg.createSVGMatrix());
				xforms.insertItemBefore(xlate, 0);
			}
			txStartX = xlate.matrix.e;
			txStartY = xlate.matrix.f;
			mouseStart = inElementSpace(evt);
			fireEvent('dragstart');

			//W3C阻止冒泡方法 
			evt = evt || window.event;
			if (evt.stopPropagation) {
				evt.stopPropagation();
			} else {
				evt.cancelBubble = true; //IE阻止冒泡方法  
			}
		}

		function handleMove(evt) {
			var point = inElementSpace(evt);
			xlate.setTranslate(
				txStartX + point.x - mouseStart.x,
				txStartY + point.y - mouseStart.y
			);
			fireEvent('drag');
		}

		function finishMove(evt) {
			root.removeEventListener('mousemove', handleMove, false);
			root.removeEventListener('mouseup', finishMove, false);
			fireEvent('dragend');
		}

		function fireEvent(eventName) {
			var event = new Event(eventName);
			event.detail = {
				x: xlate.matrix.e,
				y: xlate.matrix.f
			};
			return el.dispatchEvent(event);
		}

		// Convert mouse position from screen space to coordinates of el
		function inElementSpace(evt) {
			pt.x = evt.clientX;
			pt.y = evt.clientY;
			return pt.matrixTransform(el.parentNode.getScreenCTM().inverse());
		}
	}

	makeDraggable(document.getElementById("g1"))
	makeDraggable(document.getElementById("g2"))

	//画线	
	function makeLine(el) {
		if (!el) return console.error('makeDraggable() needs an element');
		var svg = el;
		while (svg && svg.tagName != 'svg') svg = svg.parentNode;
		if (!svg) return console.error(el, 'must be inside an SVG wrapper');
		var pt = svg.createSVGPoint(),
			doc = svg.ownerDocument;

		var root = doc.rootElement || doc.body || svg;
		var xlate, txStartX, txStartY, mouseStart;
		var xforms = el.transform.baseVal;

		el.addEventListener('mousedown', startMove, false);

		var poyline = null;

		function startMove(evt) {
			console.log("鼠标按下")
			//线的起点
			poyline = document.createElementNS(SVG_NS, 'line');

			//poyline.setAttribute('id', "polyline-id")

			let startX = evt.clientX-10;
			let startY = evt.clientY-9;
			//搜索附近的连接点，并吸附
			let nebarConnect = getNearbyConnectPoint(evt.clientX, evt.clientY);
			if (nebarConnect) {
				startX = nebarConnect.x;
				startY = nebarConnect.y;
			}
			poyline.setAttribute('x1', startX)
			poyline.setAttribute('y1', startY)
			poyline.setAttribute('x2', startX)
			poyline.setAttribute('y2', startY)
			poyline.setAttribute("style", "fill:none;stroke:#000;stroke-width:2");
			svg.appendChild(poyline);
			root.addEventListener('mousemove', handleMove, false);
			root.addEventListener('mouseup', finishMove, false);

			function handleMove(evt) {
				let endX = evt.clientX-10;
				let endY = evt.clientY-10;
				//搜索附近的连接点，并吸附
				let nebarConnect = getNearbyConnectPoint(endX, endY);
				if (nebarConnect) {
					endX = nebarConnect.x;
					endY = nebarConnect.y;
				}
				poyline.setAttribute("x2", endX);
				poyline.setAttribute("y2", endY);
			}

			function finishMove(evt) {
				console.log("移动停止")

				let endX = evt.clientX-10;
				let endY = evt.clientY-10;
				//搜索附近的连接点，并吸附
				let nebarConnect = getNearbyConnectPoint(endX, endY);
				if (nebarConnect) {
					endX = nebarConnect.x;
					endY = nebarConnect.y;
				}
				poyline.setAttribute("x2", endX);
				poyline.setAttribute("y2", endY);

				root.removeEventListener('mousemove', handleMove, false);
				root.removeEventListener('mouseup', finishMove, false);
				//fireEvent('dragend');
			}

			function fireEvent(eventName) {
				var event = new Event(eventName);
				event.detail = {
					x: xlate.matrix.e,
					y: xlate.matrix.f
				};
				return el.dispatchEvent(event);
			}

			// Convert mouse position from screen space to coordinates of el
			function inElementSpace(evt) {
				// pt.x = evt.clientX;
				// pt.y = evt.clientY;
				// return pt.matrixTransform(el.parentNode.getScreenCTM().inverse());
			}
		}
	}

	/**
	 * 搜索最近的连接点
	 * @param {Object} x
	 * @param {Object} y
	 */
	function getNearbyConnectPoint(x, y) {
		let cps = document.getElementsByTagName("circle");
		for (let i = 0; i < cps.length; i++) {
			let cp = cps[i];
			let cpX = cp.getAttribute("cx");
			let cpY = cp.getAttribute("cy");
			console.log("X:" + x + "附近目标：" + cpX)
			console.log("Y:" + y + "附近目标：" + cpY)
			if (Math.abs(cpX - x) < 20 && Math.abs(cpY - y) < 20) {
				return {
					x: cpX,
					y: cpY
				};
			}
		}
		return null;
	}
	makeLine(document.getElementById("s"))
</script>
